
#ifndef _TIMER_H_
#define _TIMER_H_


#include <cstdint>
#include <memory>
#include <set>
#include <shared_mutex>
#include <cassert>
#include <functional>
#include <mutex>
#include <vector>


namespace zepco {

class TimerManager;

class Timer : public std::enable_shared_from_this<Timer> {
  public:
    // 从定时器中删除timer
    bool cancel();
    // 刷新teimer
    bool refresh();
    // 重设当前时间
    bool reset(uint64_t ms, bool from_now);

  private:
    Timer(uint64_t ms, std::function<void()> callback, bool recurring, TimerManager *manger);

  private:
    friend class TimerManager;

    // 是否循环
    bool m_recurring = false;
    // 超时时间
    uint64_t m_ms;
    // 绝对超时时间 即定时器的下一次触发的时间点
    std::chrono::time_point<std::chrono::system_clock> m_next;
    std::function<void()> m_callback;
    // 管理此Timer的管理器
    TimerManager *m_manger = nullptr;

    struct Comparator {
        bool operator()(const std::shared_ptr<Timer> &lhs, const std::shared_ptr<Timer> &rhs) const;
    };

    friend bool operator<(const std::shared_ptr<Timer> &lhs, const std::shared_ptr<Timer> &rhs);

};

class TimerManager {
  public:
    TimerManager();
    virtual ~TimerManager() {}

    /**
     * @brief 添加timer
     *
     * @param ms 定时器执行间隔时间
     * @param callback 回调函数
     * @param recurring 是否循环定时器
     * @return std::shared_ptr<Timer>
     */
    std::shared_ptr<Timer> addTimer(uint64_t ms, std::function<void()> callback, bool recurring = false);
    // 添加条件timer
    std::shared_ptr<Timer> addConditionTimer(uint64_t ms, std::function<void()> callback, std::weak_ptr<void> weak_cond, bool recurring = false);
    // 从堆中拿出最近的超时时间
    uint64_t getNextTimer();

    /**
     * @brief 取出所有超时定时器的回调函数
     *
     * @param cbs [out]
     */
    void listExpiredCb(std::vector<std::function<void()>> &cbs);
    // 堆中是否有timer
    bool hasTimer();
  protected:
    // 当一个最早的timer加入堆中 --> 调用该函数
    virtual void onTimerInsertAtFront() {}
    // 添加timer
    void addTimer(std::shared_ptr<Timer> timer);

  private:
    // 当系统时间改变时 --> call
    bool deleteClockRollover();

  private:
    friend class Timer;

    std::shared_mutex m_mtx;
    // 时间堆
    std::set<std::shared_ptr<Timer>, Timer::Comparator/* std::less<> */> m_timers;
    // 在下次getNextTimer() 执行前 onTimerInsertAtFront()是否已经被触发
    bool m_tickled = false;
    // 上次检查系统时间是否回退的绝对时间
    std::chrono::time_point<std::chrono::system_clock> m_previouseTime;
};


}


#endif // _TIMER_H_